package com.cskaoyan.javase.oop1._1basic;

/**
 * 这里给出一个案例：
 * 创建学生对象，然后使用访问学生对象的属性，使用学生对象的行为。
 *
 * 要想创建学生对象
 * 首先需要创建对象的"模板"——学生类，那么如何得到一个学生类呢？
 *
 * 如何定义学生类,如何定义一个类来描述学生群体呢?
 * 定义类包括定义类本身，和定义类中结构两部分。
 * 1.定义类的结构,定义类本身:
 * 类的定义语法我们并不陌生，即：
 * [类修饰符列表] class 类名{
 *   // 类体
 * }
 * 解释:
 *      1.对于类的修饰符列表，其实也不是很多，但是限于学习进度，我们只需要知道：
 *          一个Java文件中只能定义一个public修饰的类，但是可以定义多个非public类。
 *          目前类的其他修饰符,我们可以先不了解,以后再说.
 *          一个Java文件下的所有类是什么关系? 是同包的关系
 *          而同包下不允许出现同名类
 *
 *      2.类名应该遵循大驼峰式的命名规范，类既然是描述个体的，一般多使用名词。
 *          最好见名知意。
 *
 * 约定:
 *      在实际开发中，绝大多数情况下
 *      一个Java文件里往往都只有一个和文件名相同的public class。
 *      一般是很少见定义非public class的
 *
 *      但为了上课方便，避免切换Java文件导致的麻烦，我们约定：
 *      以一个public class作为测试类，然后在下面定义非public class用于测试！
 *
 * 注意事项(非常重要,尤其对于初学者):
 * Java中的类是可以嵌套定义的
 * 即你可以把一个class定义进另一个类的类体中！这种类被称之为"内部类"！
 * 但内部类的语法，你完全不懂，一旦定义内部类可能会导致你无所适从！
 * 所以：
 * 请大家在定义类时，一定要注意看大括号，不要嵌套定义类！！！
 * 内部类的使用，我们后面自会再学习！
 * 学完内部类以后,大家可以自由根据情况定义内部类,现在不要这么做!!
 *
 *
 * 2.定义类中成员:
 * 对象具有属性和行为,而类作为模板抽取了全体对象的属性行为的共性
 * 那么类是如何来描述共性的属性和行为的呢?(重点)
 *      a.我们抽象对象全体的共有"属性"，在类中用成员变量来描述对象共性的属性。
 *          局部变量的概念: 定义在局部位置的变量就是局部变量
 *          成员变量的概念: 定义在成员位置的变量就是成员变量
 *          局部位置: 代码块,方法体等除了类体外的大括号内部都是局部位置
 *          成员位置: 类体中,只要不是局部位置,都是成员位置.也就是类体的空白处,就是成员位置
 *
 *          语法: [修饰符列表] 数据类型 成员变量名;
 *          解释:
 *              1.成员变量的修饰符列表可用的修饰符有很多，这里没有学习，我们先不管它,默认为空，不写任何修饰符即可。
 *              2.数据类型可以是基本数据类型,也可以是引用数据类型.
 *              3.成员变量名也是一个变量,要遵循小驼峰式的命名规范,见名知意.
 *
 *
 *      b.我们抽象对象全体的共有"行为"，在类中用成员方法来描述对象共性的行为。
 *      成员方法: 定义在成员位置,但修饰符列表没有static关键字修饰的方法,称之为成员方法.
 *      语法:
 *      [访问权限修饰符] 返回值类型 方法名(形参列表){
 *          // 方法体
 *      }
 *      解释:
 *          1.访问权限修饰符我们还没有学习,这里先不管它,默认是public修饰的
 *          2.其它诸如形参列表，方法体，方法名等结构和之前讲的方法一样。
 *
 * 以上,整个学生类就定义完了
 * 那么如何使用类的模板创建对象呢?创建对象之后,又如何使用呢?
 *
 * 1.对象的创建
 * 创建类的对象一般需要在方法中进行,
 * 在确定能够创建对象的地方，可以使用以下语法创建对象：
 *      类名 对象名 = new 类名();
 * 这个语法，我们并不陌生，在Scanner键盘录入的时候，已经见过了
 * 现在做如下解释：
 *      a.类名表示创建是何种对象，对象的类型是什么。
 *      b.对象名和之前讲的数组名是一个概念，都是引用数据类型的引用。
 *          作为一个变量名，对象名遵循小驼峰式的命名规范。
 *      c.new关键字表示在堆上开辟空间创建对象
 *          注意代码中的new关键字表示一定会在堆上创建一个独立的对象。
 *
 * 2,对象创建完毕后,如何使用呢?
 *      每个对象都有自身的属性和行为
 *      属性用成员变量的取值描述
 *      行为可以调用方法来体现
 *      语法:
 *          使用"对象名."成员变量名/成员方法名
 *          实际上仍然是通过引用操作对象
 *          成员变量的访问和赋值都是同样使用上述语法格式.
 *      注意/细节:
 *          a.成员变量是属于对象的,类似于数组对象中的元素,它们都是具有默认初始化,具有默认值的(默认初始化永远最先进行)
 *          如果不创建对象是不可能访问成员变量的.
 *
 *          b.成员方法也是属于对象的,如果不创建对象是不可能调用成员方法的
 *          我们将成员变量和成员方法合起来统称为类的（普通）成员,它们是属于对象的,都必须要创建对象才能够使用.
 *
 * 3,对象使用的细节问题:
 *      a.局部变量和成员变量在使用范围上的区别
 *          局部变量仅在作用域内部生效(只在大括号内部生效)
 *          但成员变量定义在类体中的成员位置,在整个类体中都生效
 *              具体来说,在类中的成员方法中可以无条件访问同类中的成员变量.
 *
 *      b.不同的对象,即便是相同类创建出来的对象
 *      它们在属性和行为上都是有可能产生差异的
 *
 *      c.对象名这个引用和之前讲的数组名引用是类似的
 *      引用都是通过存储对象的地址和对象产生联系
 *      对象是实质 但我们只能通过引用间接访问对象
 *      那么直接输出对象名会得到什么呢?
 *      在不做任何其它操作的前提下,直接打印对象名会得到一个类似下面的字符串:
 *      com.cskaoyan.javase.oop1._1basic.Student@1540e19d
 *      它是 "全限定类名 + 十六进制的地址值"
 *      注: 对于一个自定义类来说,以上结果是可以修改的
 *      当然,不同的对象引用,打印的地址值肯定是不同的
 *
 * @since 17:13
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {

    // 成员位置

    public static void main(String[] args) {
        // 局部位置
        // 在main方法当中,创建Student对象
        Student s1 = new Student();
        System.out.println(s1.age);
        System.out.println(s1.name);
        s1.age = 18;
        System.out.println(s1.age);

        s1.sleep();
        s1.study();
        s1.eat();

        System.out.println("-------------------");
        s1.stuId = "11";
        s1.name = "张三";
        s1.print();

        Student s2 = new Student();
        s2.stuId = "22";
        s2.name = "张四";
        s2.age = 19;
        s2.print();

        System.out.println(s1);
        System.out.println(s2);

        System.out.println(s1 == s2);
        Student s3 = s1;
        System.out.println(s1 == s3);
    }

    // 成员位置

}

// 学生类
class Student {
    // 定义成员变量,描述全体学生对象的共有属性
    String name;
    int age;
    String stuId;
    String grade;
    /*
        class这个单词比较特殊
        小写是一个关键字
        大写是一个JDK源码中的类
        所以为了避免产生误解
        class可以写成clazz
      */
    String clazz;

    // 定义成员方法,描述全体学生对象的共有行为
    public void sleep() {
        System.out.println("你怎么睡得着的?你这个年龄段");
    }

    public void eat() {
        System.out.println("赶紧吃完饭去学习~");
    }

    public void study() {
        System.out.println("学习Java的编程技术~~");
    }

    // 打印学生信息
    public void print() {
        System.out.println("学号是" + stuId + "的学生,名字是" + name + ",年龄是" + age);
    }

}